package cn.com.oyat.idea.service;


import cn.com.oyat.idea.controller.virtual.DeviceDescriptionController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Service
public class SsdpDiscoveryService {

    private static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250";
    private static final int UPNP_MULTICAST_PORT = 1900;

    @Value("${server.port:8191}")
    private int serverPort;

    @Autowired
    private DeviceDescriptionController deviceController;

    private MulticastSocket socket;
    private ExecutorService executorService;
    private boolean running = true;
    private String localIp;

    @PostConstruct
    public void start() {
        try {
            this.localIp = getLocalNetworkIp();
            if (this.localIp == null) {
                System.err.println("❌ 无法获取局域网IP，设备将无法被发现");
                return;
            }

            // ✅ 修复1: 创建绑定到1900端口的MulticastSocket
            socket = new MulticastSocket(UPNP_MULTICAST_PORT);
            socket.setReuseAddress(true);
            socket.setTimeToLive(4); // 增加TTL，确保跨子网（可选）

            // ✅ 修复2: 加入多播组！这是最关键的一步
            InetAddress multicastGroup = InetAddress.getByName(UPNP_MULTICAST_ADDRESS);
            socket.joinGroup(multicastGroup);

            System.out.println("✅ 成功加入SSDP多播组: " + UPNP_MULTICAST_ADDRESS);

            executorService = Executors.newSingleThreadExecutor();
            executorService.execute(this::listenForDiscoverRequests);

            sendAliveNotification();
            scheduleAliveNotifications();

            System.out.println("=========================================");
            System.out.println("🎯 DLNA虚拟设备启动成功!");
            System.out.println("📡 设备地址: http://" + localIp + ":" + serverPort);
            System.out.println("🔍 在手机APP中搜索: SpringBoot DLNA Receiver");
            System.out.println("=========================================");

        } catch (Exception e) {
            System.err.println("❌ 启动SSDP服务失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 添加定期通知方法
    private void scheduleAliveNotifications() {
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
            if (running) {
                sendAliveNotification();
            }
        }, 0, 30, TimeUnit.SECONDS); // 每30秒发送一次
    }

    @PreDestroy
    public void stop() {
        running = false;
        if (socket != null && !socket.isClosed()) {
            try {
                InetAddress multicastGroup = InetAddress.getByName(UPNP_MULTICAST_ADDRESS);
                socket.leaveGroup(multicastGroup); // ✅ 离开组播组
            } catch (Exception e) {
                e.printStackTrace();
            }
            socket.close();
        }
        if (executorService != null) {
            executorService.shutdown();
        }
        System.out.println("🛑 DLNA虚拟设备SSDP服务已停止");
    }

    private void listenForDiscoverRequests() {
        byte[] buffer = new byte[1024];

        while (running && !socket.isClosed()) {
            try {
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet);

                String request = new String(packet.getData(), 0, packet.getLength());
                String clientIp = packet.getAddress().getHostAddress();

                if (request.startsWith("M-SEARCH") && request.contains("ssdp:discover")) {
                    handleDiscoveryRequest(packet, request, clientIp);
                }

            } catch (Exception e) {
                if (running) {
                    // 正常运行时忽略socket关闭错误
                    if (!e.getMessage().contains("Socket closed")) {
                        System.err.println("❌ 接收SSDP请求错误: " + e.getMessage());
                    }
                }
            }
        }
    }

    private void handleDiscoveryRequest(DatagramPacket packet, String request, String clientIp) {
        try {
            System.out.println("🔍 收到发现请求来自: " + clientIp + ":" + packet.getPort());
            System.out.println("请求内容:\n" + request);

            String searchTarget = extractSearchTarget(request);
            System.out.println("搜索目标: " + searchTarget);

            if (isTargetMatch(searchTarget)) {
                String deviceUrl = "http://" + localIp + ":" + serverPort + "/rootdesc.xml";
                String response = buildDiscoveryResponse(searchTarget, deviceUrl);

                byte[] responseData = response.getBytes("UTF-8");
                DatagramPacket responsePacket = new DatagramPacket(
                        responseData,
                        responseData.length,
                        packet.getAddress(),
                        packet.getPort()
                );

                socket.send(responsePacket);
                System.out.println("✅ 已响应发现请求 -> " + clientIp);
                System.out.println("响应内容:\n" + response);
            } else {
                System.out.println("⚠️  忽略不匹配的搜索目标: " + searchTarget);
            }

        } catch (Exception e) {
            System.err.println("❌ 处理发现请求失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private String buildDiscoveryResponse(String searchTarget, String deviceUrl) {
        return "HTTP/1.1 200 OK\r\n" +
                "CACHE-CONTROL: max-age=1800\r\n" +
                "EXT: \r\n" +
                "LOCATION: " + deviceUrl + "\r\n" +
                "SERVER: SpringBoot/1.0 UPnP/1.0 DLNADevice/1.0\r\n" +
                "ST: " + searchTarget + "\r\n" +
                "USN: " + deviceController.getDeviceUuid() + "::" + searchTarget + "\r\n" +
                "Content-Length: 0\r\n" +
                "\r\n";
    }

    private String extractSearchTarget(String request) {
        String[] lines = request.split("\r\n");
        for (String line : lines) {
            if (line.toUpperCase().startsWith("ST:")) {
                return line.substring(3).trim();
            }
        }
        return "ssdp:all";
    }

    private boolean isTargetMatch(String searchTarget) {
        return searchTarget.contains("MediaRenderer") ||
                searchTarget.contains("ssdp:all") ||
                searchTarget.contains("upnp:rootdevice") ||
                searchTarget.equals("urn:schemas-upnp-org:device:MediaRenderer:1");
    }

    /**
     * 获取本机局域网IP地址
     */
    private String getLocalNetworkIp() {
        try {
            System.out.println("🔍 扫描网络接口...");
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

            List<String> candidateIps = new ArrayList<>();
            List<String> allIps = new ArrayList<>();

            while (interfaces.hasMoreElements()) {
                NetworkInterface iface = interfaces.nextElement();

                // 跳过回环接口和未启用的接口
                if (iface.isLoopback() || !iface.isUp()) {
                    continue;
                }

                // 跳过虚拟接口和没有广播能力的接口
                if (iface.isVirtual() || !iface.supportsMulticast()) {
                    continue;
                }

                System.out.println("📡 检查接口: " + iface.getDisplayName() + " (" + iface.getName() + ")");

                Enumeration<InetAddress> addresses = iface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress addr = addresses.nextElement();
                    if (!addr.isLoopbackAddress() && addr instanceof java.net.Inet4Address) {
                        String ip = addr.getHostAddress();
                        allIps.add(ip);
                        System.out.println("  📍 发现IP: " + ip);

                        // 优先选择WiFi和有线网络
                        if (iface.getDisplayName().toLowerCase().contains("wireless") ||
                                iface.getDisplayName().toLowerCase().contains("wlan")) {
                            System.out.println("✅ 选择WiFi接口IP: " + ip);
                            return ip;
                        }

                        if (ip.startsWith("192.168.")) {
                            candidateIps.add(0, ip); // 192.168.x.x 最优先
                        } else if (ip.startsWith("10.")) {
                            candidateIps.add(ip);
                        }
                    }
                }
            }

            // 返回优先级最高的IP
            if (!candidateIps.isEmpty()) {
                String selectedIp = candidateIps.get(0);
                System.out.println("✅ 选择候选IP: " + selectedIp);
                return selectedIp;
            }

            // 如果没有找到优选IP，返回任意一个非回环IP
            if (!allIps.isEmpty()) {
                String selectedIp = allIps.get(0);
                System.out.println("⚠️  使用备用IP: " + selectedIp);
                return selectedIp;
            }

            System.err.println("❌ 未找到可用的局域网IP地址");
            return null;

        } catch (Exception e) {
            System.err.println("❌ 获取网络接口失败: " + e.getMessage());
            return null;
        }
    }

    private int getSecondOctet(String ip) {
        try {
            String[] parts = ip.split("\\.");
            return Integer.parseInt(parts[1]);
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 主动发送alive通知
     */
    public void sendAliveNotification() {
        MulticastSocket notifySocket = null;
        try {
            // 使用 MulticastSocket 发送多播包
            notifySocket = new MulticastSocket();
            notifySocket.setTimeToLive(4); // ✅ 合法！MulticastSocket 支持

            String deviceUrl = "http://" + localIp + ":" + serverPort + "/rootdesc.xml";
            String aliveMessage = "NOTIFY * HTTP/1.1\r\n" +
                    "HOST: " + UPNP_MULTICAST_ADDRESS + ":" + UPNP_MULTICAST_PORT + "\r\n" +
                    "CACHE-CONTROL: max-age=1800\r\n" +
                    "LOCATION: " + deviceUrl + "\r\n" +
                    "NT: urn:schemas-upnp-org:device:MediaRenderer:1\r\n" +
                    "NTS: ssdp:alive\r\n" +
                    "SERVER: SpringBoot/1.0 UPnP/1.0 DLNADevice/1.0\r\n" +
                    "USN: " + deviceController.getDeviceUuid() + "::urn:schemas-upnp-org:device:MediaRenderer:1\r\n" +
                    "Content-Length: 0\r\n" +
                    "\r\n";

            byte[] aliveData = aliveMessage.getBytes("UTF-8");
            DatagramPacket alivePacket = new DatagramPacket(
                    aliveData,
                    aliveData.length,
                    InetAddress.getByName(UPNP_MULTICAST_ADDRESS),
                    UPNP_MULTICAST_PORT
            );

            notifySocket.send(alivePacket);
            System.out.println("📢 发送设备上线通知到网络");

        } catch (Exception e) {
            System.err.println("❌ 发送alive通知失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            if (notifySocket != null && !notifySocket.isClosed()) {
                notifySocket.close();
            }
        }
    }

    /**
     * 获取设备信息（用于页面显示）
     */
    public String getDeviceInfo() {
        return "IP: " + localIp + ":" + serverPort + " | UUID: " + deviceController.getDeviceUuid();
    }

    public String getLocalIp() {
        return localIp;
    }
}